﻿// NahidaProject-UnitTest-BuildExample.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#define _CRT_SECURE_NO_WARNINGS

#include <cstring>
#include <chrono>
#include <iostream>
#include <iomanip>

#include <thread>
#include <cerrno>

#include <NahidaBenchmarkTest.h>
#include <NahidaMockTest.h>
#include <NahidaUnitTest.h>

using namespace std;

class Calculator {
public:
	virtual int Add(int a, int b) = 0;
};

class MockCalculator : public Calculator {
public:
	MockMethod(int, Add, (int, int));
};

TESTCASE(BenchmarkTestTest) {
	string val = "3.141592653589793238462643383279502884";
	int count = 1000000;

	auto rt = NahidaProject::NahidaBenchmarkTest::Time(count, { {"atof", [val]() {double d = atof(val.data()); }},{"strtod", [val]() {double d = strtod(val.data(), nullptr); }},{"sscanf", [val]() {double d; sscanf(val.data(), "%lf", &d); }},{"stod", [val]() {double d = stod(val, nullptr); }} });

	auto comp = NahidaProject::NahidaBenchmarkTest::Compare(rt);
	NahidaProject::NahidaBenchmarkTest::PrintResult(comp);
	cout << endl << "runtimes in milliseconds:" << endl;
	NahidaProject::NahidaBenchmarkTest::PrintResult<chrono::milliseconds>(comp);
	cout << endl << "runtimes with min, max, mean, variance and standard deviation" << endl;
	cout << endl << "nanoseconds" << endl;
	NahidaProject::NahidaBenchmarkTest::PrintResult<chrono::nanoseconds>(rt);
	cout << endl << "microseconds" << endl;
	NahidaProject::NahidaBenchmarkTest::PrintResult<chrono::microseconds>(rt, 3);
	cout << endl << "milliseconds" << endl;
	NahidaProject::NahidaBenchmarkTest::PrintResult<chrono::milliseconds>(rt, 5);

	if (NahidaProject::NahidaBenchmarkTest::WriteResult("sample", rt)) {
		cout << endl << "successfully wrote runtimes to sample-*.txt files" << endl << endl;
	}
	else {
		cerr << endl << "there were problems: " << strerror(errno) << endl << endl;
	}
}

TESTCASE(MockTestTest) {
	MockCalculator calculator;
	When(calculator.Add).Return(3);
	JUDGE_EQUAL(calculator.Add(1, 2), 3);
}

TESTCASE(UnitTestMacroTest) {
	JUDGE_EQUAL(78 + 13, 91);
	JUDGE_NOTEQUAL(1 + 1, 10086);
	JUDGE_TRUE(true);
	JUDGE_FALSE(false);
	JUDGE_THROWEXCEPTION(throw std::runtime_error("This is a test exception"), std::runtime_error);
	JUDGE_TIMEOUT([]() {
		std::this_thread::sleep_for(std::chrono::seconds(3));
		}, 5000);
}

int main(int argc, char** argv) {
	NahidaProject::NahidaUnitTest::RunAllTests();
	return 0;
}

// 运行程序: Ctrl + F5 或调试 >“开始执行(不调试)”菜单
// 调试程序: F5 或调试 >“开始调试”菜单

// 入门使用技巧: 
//   1. 使用解决方案资源管理器窗口添加/管理文件
//   2. 使用团队资源管理器窗口连接到源代码管理
//   3. 使用输出窗口查看生成输出和其他消息
//   4. 使用错误列表窗口查看错误
//   5. 转到“项目”>“添加新项”以创建新的代码文件，或转到“项目”>“添加现有项”以将现有代码文件添加到项目
//   6. 将来，若要再次打开此项目，请转到“文件”>“打开”>“项目”并选择 .sln 文件
